﻿//
// File   : FiniteAutomaton.cs
// Author : Dylan Gleason
// Class  : CST229 - Grammars
// 
// FiniteAutomaton class represents a Finite
// State Machine graph, with all States and their
// transitions, as well as an initial State.
//

using System;
using System.Collections.Generic;


namespace CST229_Assignment2
{
   class FiniteAutomaton
   {
      // members
      private State m_initialState;
      private Dictionary<char, State> m_mapOfStates;

      // constructor
      public FiniteAutomaton()
      {
         m_mapOfStates = new Dictionary<char, State>();
      }

      //
      // Property lists for Finite Automata fields
      //
      public State InitialState
      {
         get { return m_initialState; }
      }

      public Dictionary<char, State> MapOfStates
      {
         get { return m_mapOfStates; }
      }

      //
      // CreateGraph method will process all input from standard
      // in and will then create a graph base on this data
      //
      public void RunTests()
      {
         int index = 0;
         string input = "";
           
         // read in each line of the file from standard input
         while ((input = Console.ReadLine()) != null)
         {
            // since the first two lines are not necessary, ignore them
            if (index > 1)
            {
               if (input.Substring(0, 2) == "F:")
               {
                  string temp = input.Substring(3);

                  string[] acceptedStates = temp.Split(new string[] { ", " },
                                                       StringSplitOptions.RemoveEmptyEntries);

                  // loop through each state which is accepted and update map
                  foreach (string i in acceptedStates)
                  {
                     char accepted = Convert.ToChar(i);
                     m_mapOfStates[accepted].IsAccepted = true;
                  }

                  // break out of loop when we are done
                  break;
               }

               // split each lines by the ',' delimiter and store in a new index
               string[] lines = input.Split(new string[] { ", " },
                                            StringSplitOptions.RemoveEmptyEntries);

               //
               // create temporary variables for the current state, the current
               // state's transition, and the state after the current state's
               // transition.
               //
               char currentState = Convert.ToChar(lines[0]);
               char transition = Convert.ToChar(lines[1]);
               char stateAfterTransition = Convert.ToChar(lines[2]);

               // if we've reached the third line, we are on the initial state
               if (index == 2)
               {
                  m_initialState = new State(currentState);
                  m_mapOfStates.Add(currentState, m_initialState);
               }

               // if the current state is not already in the map, create it
               if (!m_mapOfStates.ContainsKey(currentState))
               {
                  m_mapOfStates.Add(currentState, new State(currentState));
               }

               // if the state after transition is not in the map, create it
               if (!m_mapOfStates.ContainsKey(stateAfterTransition))
               {
                  m_mapOfStates.Add(stateAfterTransition,
                                    new State(stateAfterTransition));
               }

               // if a, set current State's aTransition to state after a transition
               if (transition == 'a')
               {
                  m_mapOfStates[currentState].TransitionA =
                     m_mapOfStates[stateAfterTransition];
               }
               // else set current State's bTransition to state after b transition
               else
               {
                  m_mapOfStates[currentState].TransitionB =
                     m_mapOfStates[stateAfterTransition];
               }
            }

            ++index;
         }

         Console.WriteLine("\nTesting:\n");
         TestStrings();
      }

      //
      // TestEachString should read in each string and then call the initial
      // state's test method for each string.
      // 
      private void TestStrings()
      {
         string input;

         while ((input = Console.ReadLine()) != null)
         {
            // validate the input string by calling State's Test method
            if (InitialState.Test (input))
               Console.WriteLine("ACCEPT\n");
            else
               Console.WriteLine("REJECT\n");
         }
      }
   }
}
